<?php
/**
 * Author: Hancock
 * Email: 84622365@qq.com
 * Date: 3/24/2016
 * Des: 模型类
 */
defined('INHkMvc') or exit('Access Invalid!');

class Model
{
    protected $table;
    protected $config;
    protected $tables = [];
    protected $alia = "";
    protected $alias = [];
    protected $fields;
    protected $where;
    protected $limit;
    protected $group;
    protected $order;
    protected $prefixes = [];
    protected $db = '';
    protected $dbs = '';
    protected $sql = ["table" => "", "field" => "", "where" => "", "join" => "", "order" => "", "limit" => "", "group" => "", "having" => ""];
    protected $str_sql = '';
    protected $cache_model;
    protected $cache_model_path = "model";
    protected $cache_data;
    protected $data;

    public function __construct($table, $alia = false)
    {
        $this->table = strtolower($table);
        if ($alia) {
            $this->alia = $alia;
            $this->alias[] = $alia;
        }
    }

    public function setDb($db = '')
    {
        $this->config = Config::get();
        if (is_array(reset($this->config['db']))) {
            $this->dbs = $this->trimItem(explode(',', reset($this->config['db'])['db_names']));
        } else {
            $this->dbs = $this->trimItem(explode(',', $this->config['db']['db_names']));
        }
        if (!in_array(strtolower($db), $this->dbs)) {
            LD("This db:$db is not in confing");
        }
        DB::selectDb($this->db = strtolower($db));
        $this->getPreFix();
        if ($this->config['cache']['open']) {
            $this->cache_model = Factory::register("fileCache", "cache");
            $this->cache_data = Factory::register($this->config['cache']['type'] . "Cache", "cache");
        } else {
            $this->cache_model = $this->cache_data = false;
        }
    }

    public function __call($method_name, $args)
    {
        $method_name = strtolower($method_name);
        if (array_key_exists($method_name, $this->sql)) {
            if (empty($args[0]) || (is_string($args[0]) && trim($args[0]) === '')) {
                $this->sql[$method_name] = "";
            } else {
                $this->sql[$method_name] = $args;
            }

            if ($method_name == "limit") {
                if ($args[0] == "0") {
                    $this->sql[$method_name] = $args;
                }
            }
        }
        return $this;
    }

    /**
     * 清空参数
     */
    protected function setNull()
    {
        $this->sql = ["table" => "", "field" => "", "where" => "", "join" => "", "order" => "", "limit" => "", "group" => "", "having" => ""];
    }

    /**
     * 拼接表
     * @return array|bool
     */
    protected function tableItem()
    {
        $tables = [];
        if (!empty($this->sql['table'])) {
            if (is_string($this->sql['table'][0])) {
                $tables = $this->trimItem(explode(',', $this->sql['table'][0]));
            } else {
                $tables = $this->sql['table'][0];
            }
        }
        array_unshift($tables, $this->table);
        $this->tables = implode(',' . SPACE, $this->getTablesName($tables));

    }

    /**
     * 获取全部查询表的全名
     * @param $tables
     * @return bool
     */
    protected function getTablesName($tables)
    {
        foreach ($tables as $key => &$table) {
            if ($key == 0) {
                $table = $this->defaultPrefix() . $table . DB_FIELD_SEP;
                if ($this->alia != '') {
                    $table .= SPACE . 'as' . SPACE . $this->alia;
                }
            } else {
                $items = explode(".", $table);
                if (count($items) == 2) {
                    if (strstr($items[1], SPACE)) {
                        $item = explode(SPACE, $items[1]);
                        $table = DB_FIELD_SEP . $items[0] . DB_FIELD_SEP . '.' . DB_FIELD_SEP . $this->prefixes[$items[0]][0] . $item[0] . DB_FIELD_SEP . SPACE . 'as' . SPACE . $item[1];
                        $this->alias[] = $item[1];
                    } else {
                        $table = DB_FIELD_SEP . $items[0] . DB_FIELD_SEP . '.' . DB_FIELD_SEP . $this->prefixes[$items[0]][0] . $items[1] . DB_FIELD_SEP;
                    }
                } elseif (count($items) == 1) {
                    if (strstr($items[0], SPACE)) {
                        $item = explode(SPACE, $items[0]);
                        $table = $this->defaultPrefix() . $item[0] . DB_FIELD_SEP . SPACE . 'as' . SPACE . $item[1];
                        $this->alias[] = $item[1];
                    } else {
                        $table = $this->defaultPrefix() . $items[0] . DB_FIELD_SEP;
                    }
                } else {
                    return false;
                }
            }
        }
        return $tables;
    }

    /**
     * 获取表前缀
     */
    protected function getPreFix()
    {
        if (is_array(reset($this->config['db']))) {
            foreach ($this->dbs as $db) {
                if (!array_key_exists("db_prefix_" . $db, reset($this->config['db']))) {
                    LD("This db: db_prefix_" . $db . " is not in db.ini");
                }
                $this->prefixes[$db] = reset($this->config['db'])["db_prefix_" . $db];
            }
        } else {
            foreach ($this->dbs as $db) {
                if (!array_key_exists("db_prefix_" . $db, $this->config['db'])) {
                    LD("This db: db_prefix_" . $db . " is not in db.ini");
                }
                $this->prefixes[$db][] = $this->config['db']["db_prefix_" . $db];
            }
        }
    }

    /**
     * 获取默认表前缀
     * @return string
     */
    private function defaultPrefix()
    {
        $default_prefix = DB_FIELD_SEP . $this->db . DB_FIELD_SEP . '.' . DB_FIELD_SEP;
        $default_prefix .= $this->prefixes[$this->db][0];
        return $default_prefix;
    }

    /**
     * 去空格
     * @param $items
     * @return mixed
     */
    protected function trimItem($items)
    {
        if (!empty($items)) {
            foreach ($items as &$item) {
                $item = trim($item);
            }
        }
        return $items;
    }

    /**
     * 操作符
     * @param $value
     * @return bool|string
     */
    protected function op($value)
    {
        $value = strtoupper($value);
        switch ($value) {
            case 'EQ':
                $op = '=';
                break;
            case 'NEQ':
                $op = '<>';
                break;
            case 'GT':
                $op = '>';
                break;
            case 'EGT':
                $op = '>=';
                break;
            case 'LT':
                $op = '<';
                break;
            case 'ELT':
                $op = '<=';
                break;
            case 'NOTLIKE':
                $op = 'NOT LIKE';
                break;
            case '=':
            case '<>':
            case '>':
            case '>=':
            case '<':
            case '<=':
            case 'NOT LIKE':
            case 'LIKE':
            case 'IN':
            case 'NOT IN':
            case 'AND':
            case 'OR':
            case 'BETWEEN':
            case 'EXP':
                $op = $value;
                break;
            default:
                LD($this->table . ' where_item ' . $value . 'is unavailable.');
                return false;
                break;
        }
        return $op;
    }

    /**
     * where子项解析
     * @param $key
     * @param $val
     * @param bool|true $flag
     * @return string
     */
    protected function whereItem($key, $val, $flag = true)
    {
        $where_str = '';
        if (is_array($val)) {
            if (sizeof($val) == 1) {
                $val[3] = 1;
                $val[2] = 'AND';
                $val[1] = $val[0];
                $val[0] = 'EQ';
            }
            $op = $this->op($val[0]);
            $value = $val[1];
            $rule = $flag ? (isset($val[2]) ? $val[2] : 'AND') : '';
            $is_field = isset($val[3]) ? $val[3] : 0;

            switch ($op) {
                case 'IN':
                case 'NOT IN':
                    $where_str .= SPACE . $rule . SPACE . trim($this->getFullFieldName($key), ', ') . SPACE . $op . SPACE . "(" . $value . ")";
                    break;
                case 'AND':
                case 'OR':
                    $key2 = array_shift($value[1]);
                    $where_str .= SPACE . $rule . SPACE . "(" . $this->whereItem($key, $value[0], false) . SPACE . $op . $this->whereItem($key2, $value[1], false) . SPACE . ")";
                    break;
                case 'BETWEEN':
                    $where_str .= SPACE . $rule . SPACE . "(" . SPACE . trim($this->getFullFieldName($key), ', ') . SPACE . $op . SPACE . $this->parseValue($value[0]) . SPACE . 'AND' . SPACE . $this->parseValue($value[1]) . SPACE . ")";
                    break;
                case 'EXP':
                    $where_str .= SPACE . $rule . SPACE . $value;
                    break;
                default:
                    $where_str .= SPACE . $rule . SPACE . trim($this->getFullFieldName($key), ', ') . SPACE . $op . SPACE . ($is_field ? trim($this->getFullFieldName($value), ', ') : $this->parseValue($value));
                    break;
            }
        } else {
            $where_str .= SPACE . 'AND' . SPACE . $this->getFullFieldName($key) . ' = ' . $this->parseValue($val);
        }
        return $where_str;
    }

    /**
     * 拼接where
     */
    protected function setWhere($where = [])
    {
        if (!empty($this->sql['where'])) {
            $where = $this->sql['where'][0];
        }
        $str = '';
        if (!is_array($where)) {
            $str = $where;
        } else {
            $str = '';
            foreach ($where as $key => $value) {
                if (is_array($value)) {
                    if (is_string($key)) {
                        $str .= $this->whereItem($key, $value);
                    } else {
                        foreach ($value as $k => $v) {
                            $str .= $this->whereItem($k, $v);
                        }
                    }
                } else {
                    $str .= $this->whereItem($key, $value);
                }
            }
        }
        $this->where = ltrim(ltrim(trim($str), "AND" . SPACE), "OR" . SPACE);
    }

    /**
     * 拼接
     * @param $data
     */
    public function setData($data)
    {
        $this->data = $this->paramsFilter($data);
    }

    /**
     * 拼接join
     */
    protected function joinItem()
    {
        if (!empty($this->sql['join'])) {
            $tables = explode(', ', $this->tables);
            foreach ($this->sql['join'][0] as $key => $value) {
                $str = '';
                $join = SPACE . strtoupper(array_shift($value)) . SPACE . 'JOIN';
                if (!in_array($key, $this->alias)) {
                    $key = $this->getFullTableName($key);
                }
                foreach ($value as $v) {
                    $field_path = $this->getFullTableName($v[1]);
                    if (strstr($field_path, SPACE . 'as' . SPACE)) {
                        $this->alias[] = str_replace(DB_FIELD_SEP, '', explode(SPACE . 'as' . SPACE, $field_path)[1]);
                    }
                    $str .= $join . SPACE . $field_path . SPACE . 'on' . SPACE . $this->getFullFieldName($v[0]) . SPACE . '=' . SPACE . $this->getFullFieldName($v[2]);
                    if (sizeof($v) > 3) {
                        for ($i = 3; $i < sizeof($v); $i++) {
                            foreach ($v[$i] as $k => $vv) {
                                $str .= $this->whereItem($k, $vv);
                            }
                        }
                    }
                }
                foreach ($tables as &$table) {
                    if (strstr($table, SPACE . 'as' . SPACE . $key) || ($table == $key)) {
                        $table = $table . $str;
                    }
                }
            }
            $this->tables = implode(', ', $tables);
        }
    }

    /**
     * 获取表的全名
     * @param $table
     * @return string
     */
    protected function getFullTableName($table)
    {
        $full_table_name = '';
        $alia = '';
        if (strstr($table, SPACE)) {
            $alia = explode(SPACE, $table)[1];
            $table = explode(SPACE, $table)[0];
        }
        if (strstr($table, '.')) {
            $items = explode('.', $table);
            $full_table_name .= DB_FIELD_SEP . $items[0] . DB_FIELD_SEP . '.';
            $flag = 1;
            if (empty($this->prefixes[$items[0]])) {
                return false;
            }
            foreach ($this->prefixes[$items[0]] as $prefix) {
                if (empty($prefix)) break;
                if (strstr($items[1], $prefix)) {
                    $flag = 0;
                    $full_table_name .= DB_FIELD_SEP . $items[1] . DB_FIELD_SEP;
                    break;
                }
            }
            if ($flag) {
                $full_table_name .= DB_FIELD_SEP . $this->prefixes[$items[0]][0] . $items[1] . DB_FIELD_SEP;
            }
        } else {
            $flag = 1;
            foreach ($this->prefixes[$this->db] as $prefix) {
                if (empty($prefix)) break;
                if (strstr($table, $prefix)) {
                    $flag = 0;
                    $full_table_name .= DB_FIELD_SEP . $this->db . DB_FIELD_SEP . '.' . DB_FIELD_SEP . $table . DB_FIELD_SEP;
                    break;
                }
            }
            if ($flag) {
                $full_table_name .= $this->defaultPrefix() . $table . DB_FIELD_SEP;
            }
        }
        if ($alia != '') {
            $full_table_name .= SPACE . 'as' . SPACE . $alia;
        }
        return $full_table_name;
    }

    /**
     * 获取字段全名
     * @param $column
     * @return string
     */
    protected function getFullFieldName($column)
    {
        if (strstr($column, '.')) {
            $items = explode('.', $column);
            if (count($items) == 3) {
                if (strstr($items[2], SPACE)) {
                    return $this->getFullTableName($items[0] . '.' . $items[1]) . '.' . DB_FIELD_SEP . trim(strstr($items[2], SPACE, true)) . DB_FIELD_SEP . SPACE . trim(strstr($items[2], SPACE));
                } else {
                    return $this->getFullTableName($items[0] . '.' . $items[1]) . '.' . $items[2];
                }
            } elseif (count($items) == 2) {
                if (in_array($items[0], $this->alias)) {
                    if (strstr($items[1], SPACE)) {
                        return $items[0] . '.' . DB_FIELD_SEP . trim(strstr($items[1], SPACE, true)) . DB_FIELD_SEP . SPACE . trim(strstr($items[1], SPACE));
                    } else {
                        return $items[0] . '.' . $items[1];
                    }

                } else {
                    if (strstr($items[1], SPACE)) {
                        return $this->getFullTableName($items[0]) . '.' . DB_FIELD_SEP . trim(strstr($items[1], SPACE, true)) . DB_FIELD_SEP . SPACE . trim(strstr($items[1], SPACE));
                    } else {
                        return $this->getFullTableName($items[0]) . '.' . $items[1];
                    }

                }
            }
        } else {
            if ($this->alia == false) {
                if (strstr($column, SPACE)) {
                    return $this->defaultPrefix() . $this->table . DB_FIELD_SEP . '.' . DB_FIELD_SEP . trim(strstr($column, SPACE, true)) . DB_FIELD_SEP . SPACE . trim(strstr($column, SPACE));
                } else {
                    return $this->defaultPrefix() . $this->table . DB_FIELD_SEP . '.' . $column;
                }

            } else {
                if (strstr($column, SPACE)) {
                    return $this->alia . '.' . DB_FIELD_SEP . trim(strstr($column, SPACE, true)) . DB_FIELD_SEP . SPACE . trim(strstr($column, SPACE));
                } else {
                    return $this->alia . '.' . $column;
                }

            }
        }
    }

    /**
     * 过滤字符串
     * @param $value
     * @return string
     */
    protected function parseValue($value)
    {
        return '\'' . htmlspecialchars(addslashes(stripslashes($value))) . '\'';
    }

    /**
     * 拼接字段
     */
    protected function fieldItem()
    {
        $fields = '';
        if (!empty($this->sql['field'])) {
            if (is_string($this->sql['field'][0])) {
                foreach (explode(',', $this->sql['field'][0]) as $field) {
                    $fields .= $this->getFullFieldName(trim($field)) . ', ';
                }
            } else {
                foreach ($this->sql['field'][0] as $field) {
                    $fields .= $this->getFullFieldName($field) . ', ';
                }
            }
            $this->fields = rtrim($fields, ', ');
        } else {
            $this->fields = '*';
        }
    }

    /**
     * 拼接group by
     */
    protected function groupItem()
    {
        $this->group = "";
        if (!empty($this->sql['group'])) {
            $group_str = '';
            if (is_string($this->sql['group'][0])) {
                $groups = explode(',', $this->sql['group'][0]);
                $group_str = '';
            } else {
                $groups = $this->sql['group'][0];
            }
            foreach ($groups as $value) {
                $group_str .= $this->getFullFieldName($value);
                $group_str .= ',';
            }

            $this->group = rtrim($group_str, ',');
        }
    }

    /**
     * 拼接order by
     * @return bool
     */
    protected function orderItem()
    {
        $this->order = "";
        if (!empty($this->sql['order'])) {
            if (is_string($this->sql['order'][0])) {
                $orders = explode(',', $this->sql['order'][0]);
            } else {
                $orders = $this->sql['order'][0];
            }
            $order_str = '';
            foreach ($orders as $order) {
                $order_field = explode(SPACE, $this->mergeSpaces($order));
                if (sizeof($order_field) > 2) {
                    return false;
                }
                if (sizeof($order_field) > 0) {
                    $order_str .= $this->getFullFieldName($order_field[0]);
                }
                if (sizeof($order_field) > 1) {
                    $order_str .= SPACE . $order_field[1];
                }
                $order_str .= ',';
            }
            $this->order = rtrim($order_str, ',');
        }
    }

    /**
     * 拼接limit
     */
    protected function limitItem()
    {
        $this->limit = "";
        if (!empty($this->sql['limit'])) {
            $this->limit = $this->sql['limit'][0];
            if (isset($this->sql['limit'][1])) {
                $this->limit .= ',' . $this->sql['limit'][1];
            }
        }
    }

    /**
     * 获取所有结果集
     * @param array $where
     * @return mixed
     */
    public function select($where = [])
    {
        $sql = $this->sql($where);
        //echo $sql;die;
        return DB::fetchAll($sql);
    }

    /**
     * 获取一条结果集
     * @param array $where
     * @return bool
     */
    public function find($where = [])
    {
        $sql = $this->sql($where, true);
        //echo $sql;die;
        $res = DB::fetchAll($sql);
        if ($res === false || count($res) == 0) {
            return false;
        } else {
            return $res[0];
        }
    }

    /**
     * 拼接sql语句
     */
    protected function sql($where = [], $is_find = false)
    {
        $sql = '';
        $this->tableItem();
        $this->joinItem();
        $this->setWhere($where);
        $this->fieldItem();
        $this->limitItem();
        $this->groupItem();
        $this->orderItem();
        $sql .= "SELECT" . SPACE . $this->fields . SPACE . "FROM" . SPACE . $this->tables;
        if (!empty($this->where)) {
            $sql .= SPACE . "WHERE" . SPACE . $this->where;
        }
        if (!empty($this->group)) {
            $sql .= SPACE . "GROUP BY" . SPACE . $this->group;
        }
        if (!empty($this->order)) {
            $sql .= SPACE . "ORDER BY" . SPACE . $this->order;
        }
        if ($is_find) {
            $sql .= SPACE . "Limit" . SPACE . 1;
        } else {
            if (!empty($this->limit)) {
                $sql .= SPACE . "Limit" . SPACE . $this->limit;
            }
        }
        $this->setNull();
        $this->str_sql = $sql;
        return $sql;
    }

    /**
     * 获取sql语句
     * @return string
     */
    public function getSql()
    {
        return $this->str_sql;
    }

    /**
     * 返回错误信息
     * @return mixed
     */
    public function error()
    {
        return DB::error();
    }

    public function total()
    {
        $where = "";
        $data = [];
    }

    /**
     * 去多余的空格
     * @param $string
     * @return mixed
     */
    protected function mergeSpaces($string)
    {
        return preg_replace("/\s(?=\s)/", "\\1", $string);
    }

    /**
     * 参数过滤
     * @param $params
     * @return array|bool
     */
    public function paramsFilter($params)
    {
        if ($columns = $this->getColumns()) {
            $data = array();
            foreach ($columns as $column) {
                $type = explode('(', $column['Type']);
                if (sizeof($type) > 1) {
                    $length = explode(')', $type[1])[0];
                }
                $type = $type[0];
                if (array_key_exists($column['Field'], $params)) {
                    $data[$column['Field']] = $this->columnFilter($type, $params[$column['Field']]);
                    if ($data[$column['Field']] === false) {
                        return false;
                    }
                } else {
                    continue;
                }
            }
            return $data;
        } else {
            return false;
        }
    }

    /**
     * 数据库字段过滤
     * @param $type
     * @param $value
     * @return bool|string
     */
    protected function columnFilter($type, $value)
    {
        switch ($type) {

            /**
             * int型数据处理
             */
            case 'int':
            case 'tinyint':
            case 'smallint':
            case 'mediumint':
            case 'integer':
            case 'bigint':
            case 'bit':
                return intval($value);
                break;
            case 'double':
            case 'float':
            case 'decimal':
            case 'real':
            case 'numeric':
                return doubleval($value);
                break;

            /**
             * string型数据处理
             */
            case 'char':
            case 'varchar':
            case 'tinytext':
            case 'text':
            case 'mediumtext':
            case 'longtext':
            case 'tinyblob':
            case 'blob':
            case 'mediumblob':
            case 'longblob':
                return trim($value);
                break;

            /**
             * time型数据处理
             */
            case 'time':
                $format = 'H:i:s';
            case 'date':
                $format || $format = 'Y-m-d';
            case 'datetime':
            case 'timestamp':
                $format || $format = 'Y-m-d H:i:s';
                if (!is_string($value)) {
                    $value = date($format, $value);
                }
                if (strtotime($value)) {
                    return $value;
                } else {
                    return false;
                }
                break;
            case 'enum':
            case 'set':
            case 'binary':
            case 'varbinary':
            case 'point':
            case 'linestring':
            case 'polygon':
            case 'geometry':
            case 'multipoint':
            case 'multilinestring':
            case 'multipolygon':
            case 'geometrycollection':
                return $value;
                break;

            /**
             * 默认处理类型
             */
            default:
                return false;
                break;
        }
    }

    /**
     * 获取数据库字段
     * @return bool
     */
    public function getColumns()
    {
        if ($this->table) {
            $key = $this->table . "fields";
            $columns = $this->readCache($key, 'model');
            if (!$columns) {
                $sql = "SHOW FULL COLUMNS FROM " . $this->getFullTableName($this->table);
                $columns = DB::fetchAll($sql);
                if ($columns !== false) {
                    $this->writeCache($key, $columns, 15768000, 'model');
                } else {
                    return false;
                }
            }
            return $columns;
        } else {
            return false;
        }
    }

    /**
     * 写缓存
     * @param $key
     * @param $data
     * @param int $time
     * @param string $path
     * @return bool
     */
    public function writeCache($key, $data, $time = 0, $path = '')
    {
        if ($path == "data") {
            if ($this->cache_data->isWrite()) {
                echo "yes";
            }
        } else {
            if ($this->cache_model->isWrite($this->config['cache'])) {
                return $this->cache_model->write($key, $data, $time, $path);
            } else {
                return false;
            }
        }
    }

    /**
     * 读缓存
     * @param $key
     * @param $path
     * @return mixed
     */
    public function readCache($key, $path = '')
    {
        if ($path == "data") {

        } else {
            return $this->cache_model->read($key, $path);
        }
    }

    public function update($data = [], $where = false, $inc_array = [])
    {
        if ($data) {
            $this->setData($data);
        }
        if ($where) {
            $this->setWhere($where);
        }
        if (DB::query($this->getUpdateSql($inc_array))) {
            return DB::affectedRows();
        } else {
            return false;
        }
    }

    protected function getUpdateSql($inc_array = [])
    {
        if (!empty($this->where)) {
            $where = ' WHERE ' . ltrim($this->where, ' AND ');
            $values = '';
            foreach ($this->data as $key => $value) {
                if (isset($inc_array[$key])) {
                    $values .= $this->getFullFieldName($key) . '= ' . $this->getFullFieldName($key) . $inc_array[$key] . $value . ' ,';
                } else {
                    $values .= $this->getFullFieldName($key) . '=\'' . addslashes($value) . '\',';
                }
            }
            return 'UPDATE ' . $this->getFullTableName($this->table) . ' SET ' . rtrim($values, ',') . $where;
        } else {
            $values = '';
            foreach ($this->data as $key => $value) {
                if (isset($inc_array[$key])) {
                    $values .= $this->getFullFieldName($key) . '= ' . $this->getFullFieldName($key) . $inc_array[$key] . $value . ' ,';
                } else {
                    $values .= $this->getFullFieldName($key) . '=\'' . addslashes($value) . '\',';
                }
            }
            return 'UPDATE ' . $this->getFullTableName($this->table) . ' SET ' . rtrim($values, ',');
        }
    }

    public function insert($data)
    {
        if ($data) {
            $this->setData($data);
        }
        if (empty($this->data)) {
            return false;
        }
        if (DB::query($this->getInsertSql())) {
            return DB::insertId();
        }
        return false;
    }

    protected function getInsertSql()
    {
        $column = '';
        $values = '';
        foreach ($this->data as $key => $value) {
            $column .= '`' . $key . '`,';
            $values .= '\'' . addslashes($value) . '\',';
        }
        return 'INSERT INTO ' . $this->getFullTableName($this->table) . '(' . rtrim($column, ',') . ') VALUES(' . rtrim($values, ',') . ');';
    }

    public function begin()
    {
        DB::begin();
    }

    public function commit()
    {
        DB::commit();
    }

    public function rollback()
    {
        DB::rollback();
    }

    public function getCountSql($where = array())
    {
        $sql = $this->sql($where);
        return str_replace('Limit ' . $this->limit, '', $sql);
    }

    public function count($where = array())
    {
        if (!empty($where)) {
            $sql_count = trim($this->getCountSql($where));
        } else {
            $sql_count = trim($this->getCountSql($this->where));
        }
        //echo $sql_count;die;
        $res = DB::fetchAll($sql_count);
        if ($res === false) {
            return false;
        }
        return count($res);
    }

    public function getCountSqls()
    {
        $sql = $this->str_sql;
        return str_replace('Limit ' . $this->limit, '', $sql);
    }

    public function counts($where = array())
    {
        if (!empty($where)) {
            $sql_count = trim($this->getCountSql($where));
        } else {
            $sql_count = trim($this->getCountSqls());
        }
        //echo $sql_count;die;
        $res = DB::fetchAll($sql_count);
        if ($res === false) {
            return false;
        }
        return count($res);
    }

    /**
     * 分页
     * eg:page(url('test','test').'&p=',$count=1000,$current,10,$tpl='',$num=9);
     * @param $url
     * @param int $count
     * @param int $current
     * @param int $page_size
     * @param string $tpl
     * @param int $num
     * @return array
     */
    public function page($url, $count = 0, $current = 1, $page_size = 10, $tpl = '', $num = 10)
    {
        $data = array();
        if (empty($tpl)) {
            $tpl = array(
                'prev' => '<a href="%url%" aria-label="Previous"><i class="icon icon-chevron-left"></i></a>',
                'next' => '<a href="%url%" aria-label="Next"><i class="icon icon-chevron-right"></i></a>',
                'current' => '<a class="active" href="javascript:;">%current%</a>',
                'page' => '<a href="%url%">%page%</a>',
            );
        }

        $current = ($current) ? $current : 1;

        //总条数
        if (!$count) {
            $count = $this->count();
            if (!$count) {
                return false;
            }
        }

        //总页数
        $page_count = ceil($count / $page_size);

        $data['current'] = $current;
        $data['count'] = $page_count;

        //上一页
        if ($current > 1) {
            $prev_page = $current - 1;
        } else {
            $prev_page = 1;
        }
        //下一页
        if ($current < $page_count) {
            $next_page = $current + 1;
        } else {
            $next_page = $page_count;
        }

        if (($current - 1) < ($num / 2)) {
            $start = 1;
            $end = $page_count > $num ? $num : $page_count;
        } elseif (($page_count - $current) < ($num / 2)) {
            $end = $page_count;
            $start = $page_count > $num ? ($page_count - $num + 1) : 1;
        } else {
            $start = $current - ceil($num / 2);
            $end = $current + intval($num / 2);
        }

        $content = '';

        if ($prev_page != $current) {
//    		$html = str_replace("%url%",$url.$prev_page,$tpl['pre']);
//    		$content .= $html;
            $data['links'][] = str_replace("%url%", $url . $prev_page, $tpl['prev']);
        }

        for ($i = $start; $i <= $end; $i++) {
            if ($i == $current) {
//    			$html=str_replace("%current%",$i,$tpl['current']);
//    			$content.=$html;
                $data['links'][] = str_replace("%current%", $i, $tpl['current']);
            } else {
                $search = array("%url%", "%page%");
                $replace = array($url . $i, $i);
                $data['links'][] = str_replace($search, $replace, $tpl['page']);
            }
        }

        if ($next_page != $current) {
            $data['links'][] = str_replace("%url%", $url . $next_page, $tpl['next']);
        }

        return $data;
    }

    protected function getDeleteSql()
    {
        if (!empty($this->where)) {
            $where = ' WHERE ' . $this->where;
            return "DELETE FROM" . SPACE . $this->getFullTableName($this->table) . $where;
        } else {
            return false;
        }
    }

    public function delete($where = [])
    {
        if ($where) {
            $this->setWhere($where);
        }
//         echo $this->getDeleteSql();die;
        if (DB::query($this->getDeleteSql())) {
            return DB::affectedRows();
        }
        return false;
    }
}
